#pragma once

#include "Den_Lib_Config.h"

namespace Den{

struct SEmpty;

template<class T>struct TReturnValue
{ 
    typedef T Type_t;
    TReturnValue(){ FOR_TESTING(std::cout<<"TReturnValue<T> was build\n");   }
    void operator=(const T& src)const { mData=src; }
    T& Return()const { return mData; } 
    mutable T mData;
};

template<>struct TReturnValue<void>
{
    typedef void Type_t; 
    TReturnValue(){ FOR_TESTING(std::cout<<"TReturnValue<void> was build\n");   }
};
template<>struct TReturnValue<SEmpty>
{
    typedef SEmpty Type_t; 
    TReturnValue(){ FOR_TESTING(std::cout<<"TReturnValue<SEmpty> was build\n");   }
};

template<class T>struct TReturnValue<const T&> 
{
    typedef const T& Type_t; 
    TReturnValue(): mData(0l){ FOR_TESTING(std::cout<<"TReturnValue<const T&> was build\n");   }
    void operator=(const T& src)const {mData=&src; }
    const T& Return()const 
    {
        DEBUG_TEST( const bool ERROR_RETURN_VALUE_IS_EMPTY = mData==0l; assert(!ERROR_RETURN_VALUE_IS_EMPTY) );
        return *mData;
    } 
    mutable const T* mData;
};

template<class T>struct TReturnValue<T&>           
{
    typedef T& Type_t; 
    TReturnValue(): mData(0l){ FOR_TESTING(std::cout<<"TReturnValue<const T&> was build\n");   }
    void operator=(T& src)const { mData=&src; }
    T& Return()const 
    {
        DEBUG_TEST( const bool ERROR_RETURN_VALUE_IS_EMPTY = mData==0l; assert(!ERROR_RETURN_VALUE_IS_EMPTY) );
        return *mData;
    } 
    mutable T* mData;
};

template<class T, size_t N>struct TReturnValue<T (&)[N]>
{
    typedef T Type_t[N];
    TReturnValue(): mData(0l){ FOR_TESTING(std::cout<<"TReturnValue<T (&)[N]> was build\n");}
    void operator=(T (&src)[N])const { mData=&src; }
    T (&Return()const )[N]
    {
        DEBUG_TEST( const bool ERROR_RETURN_VALUE_IS_EMPTY = mData==0l; assert(!ERROR_RETURN_VALUE_IS_EMPTY) );
        return *mData;
    }
    mutable T (*mData)[N] ;
};

template<class T, size_t N>struct TReturnValue<const T (&)[N]>
{
    typedef const T Type_t[N];
    TReturnValue(): mData(0l){ FOR_TESTING(std::cout<<"TReturnValue<const T (&)[N]> was build\n");}
    void operator=(const T (&src)[N])const { mData=&src; }

    const T (&Return()const )[N]
    {
        DEBUG_TEST( const bool ERROR_RETURN_VALUE_IS_EMPTY = mData==0l; assert(!ERROR_RETURN_VALUE_IS_EMPTY) );
        return *mData;
    }

    mutable const T (*mData)[N] ;
};

//--------
} //namespace Den


